#include "serverwidget.h"
#include "ui_serverwidget.h"

#include <QDebug>
#include <unistd.h>

void ServerWidget::initServer()
{
    m_serverThread = new QThread(this);
    m_server = new Server;
    m_server->moveToThread(m_serverThread);
    m_serverThread->start();
    // 开始监听信号
    connect(this, &ServerWidget::startListen, m_server, &Server::listening);
    // 开始accept信号
    connect(this, &ServerWidget::startAccept, m_server, &Server::accepting);
    // 处理服务器listen前返回状态
    connect(m_server, &Server::serverStatus, this, &ServerWidget::dealServerTip);
    // 处理服务器accept状态(客户端套结字)
    connect(m_server, &Server::acceptStatus, this, &ServerWidget::dealAcceptFd);
}

void ServerWidget::initUi()
{
    // 应用层头部（0开始代表用户名，2代表密码，1开始代表聊天消息，3/4代表验证通过/失败）
    connect(ui->sendMsgBtn, &QPushButton::clicked, this, [=](){
        QString myMsg = ui->editBox->text();
        ui->editBox->clear();
        ui->chatBox->append("我：" + myMsg + '\n');
        // 添加应用层头部
        emit sendMsg('1' + myMsg);
    });
    connect(m_serverRead, &ServerRead::showReceivedMsg, this, [=](QString msg){
        // 解析应用层头部
        if (msg.startsWith('0'))
        {
            m_username = msg.right(msg.size() - 1);
        }
        else if (msg.startsWith('2'))
        {
            qDebug() << "unsolved psw:" << msg;
            m_password = msg.right(msg.size() - 1);
            qDebug() << m_username << m_password;
            if (m_username == "刘笑宇" && m_password == "123456")
            {
                emit sendMsg("3");
            }
            else
            {
                emit sendMsg("4");
            }
        }
        else if (msg.startsWith('1'))
        {
            msg = msg.right(msg.size() - 1);
            ui->chatBox->append("客户端：" + msg + '\n');
        }
    });

}

ServerWidget::ServerWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::ServerWidget)
{
    ui->setupUi(this);

    initServer();
    m_serverReadThread = new QThread(this);
    m_serverRead = new ServerRead;
    m_serverRead->moveToThread(m_serverReadThread);
    m_serverReadThread->start();
    connect(this, &ServerWidget::startOperate, m_serverRead, &ServerRead::reading);

    m_serverWriteThread = new QThread(this);
    m_serverWrite = new ServerWrite;
    m_serverWrite->moveToThread(m_serverWriteThread);
    m_serverWriteThread->start();
    // 主线程发信号通知读写线程运行
    connect(this, &ServerWidget::startOperate, m_serverWrite, &ServerWrite::writing);
    // 服务器端想发消息，通知写线程发消息
    connect(this, &ServerWidget::sendMsg, m_serverWrite, &ServerWrite::sendMyMsg);
    // 通知读写线程结束（特别是读线程，结束while循环）
    connect(this, &ServerWidget::stopThread, m_server, &Server::stopAccept);
    connect(this, &ServerWidget::stopThread, m_serverRead, &ServerRead::stopNow);

    initUi();

    emit startListen();
}

ServerWidget::~ServerWidget()
{
    qDebug() << "serverWidget: 开始执行析构函数";
    delete ui;

    // 为了结束accept的阻塞
    shutdown(m_serverFd, SHUT_RD);
    ::close(m_serverFd);
    shutdown(m_clientFd, SHUT_RD);
    ::close(m_clientFd);

    emit stopThread();

    qDebug() << "serverWidget: 已关闭监听套结字";

    m_serverThread->quit();
    m_serverThread->wait();
    qDebug() << "serverWidget: 服务器线程结束";
//    m_serverThread->deleteLater();

    m_serverReadThread->quit();
    m_serverReadThread->wait();
    qDebug() << "serverWidget: 服务器读线程结束";
//    m_serverReadThread->deleteLater();

    m_serverWriteThread->quit();
    m_serverWriteThread->wait();
    qDebug() << "serverWidget: 服务器写线程结束";
//    m_serverWriteThread->deleteLater();

    m_server->deleteLater();
    m_serverRead->deleteLater();
    m_serverWrite->deleteLater();
    qDebug() << "serverWidget: 析构函数执行完毕";
}

void ServerWidget::dealServerTip(int status)
{
    if (status > 0)
    {
        qDebug() << "widget know server start successed.";
        m_serverFd = status;
        emit startAccept();
    }
    else
    {
        qDebug() << "widget know server start failed.";
    }
}

void ServerWidget::dealAcceptFd(int clientFd)
{
    if (clientFd == -1)
    {
        qDebug() << "serverWidget: I know you got a -1";
    }
    else
    {
        qDebug() << "serverWidget: ready to deal" << clientFd;
        m_clientFd = clientFd;
        emit startOperate(clientFd);
    }
}
